﻿using Newtonsoft.Json;
using PLCSharp.Views.Connects.Socket;
using Prism.Mvvm;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;

namespace PLCSharp.Views.Connects
{
    public class Connect : BindableBase
    {
        [Key]
        public Guid ID { get; set; } = Guid.NewGuid();
        private string _Name;
        /// <summary>
        /// Comment
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set
            {
                if (_Name != value)
                {
                    Params. Prompt = "已修改，请保存";
                }
                SetProperty(ref _Name, value);
            }
        }

        private string _IP;
        public string IP
        {
            get { return _IP; }
            set
            {
                if (_IP != value)
                {
                    Params.Prompt = "已修改，请保存";
                }
                SetProperty(ref _IP, value);
            }
        }

        private int _Port;
        public int Port
        {
            get { return _Port; }
            set
            {
                if (_Port != value)
                {
                    Params.Prompt = "已修改，请保存";
                }
                SetProperty(ref _Port, value);
            }
        }

        private ProtocolType _Type;
        [JsonIgnore]
        /// <summary>
        /// 协议类型
        /// </summary>
        public ProtocolType Type
        {
            get { return _Type; }
            set
            {
                if (_Type == ProtocolType.Undefined)
                {
                    if (value != ProtocolType.Undefined)
                    {
                        SetProperty(ref _Type, value);

                    }
                }
                else if (_Type != value)
                {
                    MessageBox.Show("选定协议后不可改变！");
                }

            }
        }
 
        private string _Comment;
        /// <summary>
        /// 备注
        /// </summary>
        public string Comment

        {
            get { return _Comment; }
            set
            {
                if (_Comment != value)
                {
                    Params.Prompt = "已修改，请保存";
                }
                SetProperty(ref _Comment, value);
            }
        }
        #region NotMapped

        private bool _LogSwitch;
        [NotMapped]
        /// <summary>
        /// 日志开关
        /// </summary>
        public bool LogSwitch
        {
            get { return _LogSwitch; }
            set { SetProperty(ref _LogSwitch, value); }
        }
 
        private bool _Connected;
        [NotMapped]
        /// <summary>
        /// 连接成功
        /// </summary>
        public bool Connected
        {
            get { return _Connected; }
            set { SetProperty(ref _Connected, value); }
        }

        private bool _Successful;
        [NotMapped]
        /// <summary>
        /// 读写成功
        /// </summary>
        public bool Successful
        {
            get { return _Successful; }
            set { SetProperty(ref _Successful, value); }
        }


        private bool _Online;
        [NotMapped]
        /// <summary>
        /// 在线
        /// </summary>
        public bool Online
        {
            get { return _Online; }
            set { SetProperty(ref _Online, value); }
        }

        private string _ReceiveInfo;
        [NotMapped]
        /// <summary>
        /// 收到的信息
        /// </summary>
        public string ReceiveInfo
        {
            get { return _ReceiveInfo; }
            set { SetProperty(ref _ReceiveInfo, value); }
        }


        private byte[] _ReceiveData;
        [NotMapped]
        /// <summary>
        /// 收到的数据
        /// </summary>
        public byte[] ReceiveData
        {
            get { return _ReceiveData; }
            set { SetProperty(ref _ReceiveData, value); }
        }
        private string _SendInfo;
        [NotMapped]
        /// <summary>
        /// 要发送的信息
        /// </summary>
        public string SendInfo
        {
            get { return _SendInfo; }
            set { SetProperty(ref _SendInfo, value); }
        }

        [Column("Params")]
        public string SerializedParams
        {
            get => JsonConvert.SerializeObject(Params); // 自动序列化
            set => Params = JsonConvert.DeserializeObject<ConnectParams>(value); // 自动反序列化

        }
        private ConnectParams _Params;
        [NotMapped]
        /// <summary>
        /// Comment
        /// </summary>
        public ConnectParams Params
        {
            get
            {
                _Params ??= new ConnectParams();

                return _Params;
            }
            set
            {
                SetProperty(ref _Params, value);
            }
        }

        private ObservableCollection<Connect> _Clients = [];
        [NotMapped]
        /// <summary>
        /// 连接 服务器 的 客户端
        /// </summary>
        public ObservableCollection<Connect> Clients
        {
            get { return _Clients; }
            set { SetProperty(ref _Clients, value); }
        }

        [Column("Clients")]
        public string SerializedClients
        {
            get => JsonConvert.SerializeObject(Clients); // 自动序列化
            set => Clients = JsonConvert.DeserializeObject<ObservableCollection<Connect>>(value); // 自动反序列化

        }
 

        public virtual void Close() { }
        [NotMapped]
        public ConcurrentQueue<string> LogQueue { get; set; } = [];
        public void Log(string log)
        {
            if (LogSwitch)
            { LogQueue.Enqueue(log);

                if (LogQueue.Count > 1000)
                    LogQueue.TryDequeue(out _ );
            }
        }
        #endregion

        public virtual async Task SendAsync(string msg)
        {
            if (Params.DataType == CommunicationDataType.String)
            {
                await  SendMsgAsync(msg);

            }
            else
            {
                var sendMsg = msg.Replace(" ", "").Replace("-", "").Replace("\n", "").Replace("\r", "");
                if (sendMsg.Length % 2 != 0)
                {
                    sendMsg = "0" + sendMsg;
                }
                sendMsg = sendMsg.ToUpper();

                bool isMatch = Regex.IsMatch(sendMsg, @"^[0-9A-Fa-f]+$");
                if (isMatch)
                {

                    StringBuilder sb = new();
                    for (int i = 0; i < sendMsg.Length; i++)
                    {
                        if (i > 0 && i % 2 == 0)
                            sb.Append(' '); // 每隔两位插入空格
                        sb.Append(sendMsg[i]);
                    }
                    SendInfo = sb.ToString();
                    var split = SendInfo.Split(" ");

                    List<byte> bytes = [];
                    for (int i = 0; i < split.Length; i++)
                    {
                        bytes.Add(byte.Parse(split[i], NumberStyles.HexNumber));
                    }

                    await  SendDataAsync([.. bytes]);
                }
                else
                {
                    Log("请输入正确的十六进制字符串");
                }


            }


        }
        public virtual async Task SendAsync(string msg, string clientName)
        {

            if (this is SocketServer server)
            {
                if (Params.DataType == CommunicationDataType.String)
                {
                    await server.SendMsgAsync(msg, clientName);

                }
                else
                {
                    var sendMsg = msg.Replace(" ", "").Replace("-", "").Replace("\n", "").Replace("\r", "");
                    if (sendMsg.Length % 2 != 0)
                    {
                        sendMsg = "0" + sendMsg;
                    }
                    sendMsg = sendMsg.ToUpper();

                    bool isMatch = Regex.IsMatch(sendMsg, @"^[0-9A-Fa-f]+$");
                    if (isMatch)
                    {

                        StringBuilder sb = new();
                        for (int i = 0; i < sendMsg.Length; i++)
                        {
                            if (i > 0 && i % 2 == 0)
                                sb.Append(' '); // 每隔两位插入空格
                            sb.Append(sendMsg[i]);
                        }
                        SendInfo = sb.ToString();
                        var split = SendInfo.Split(" ");

                        List<byte> bytes = [];
                        for (int i = 0; i < split.Length; i++)
                        {
                            bytes.Add(byte.Parse(split[i], NumberStyles.HexNumber));
                        }

                        await server.SendDataAsync([.. bytes], clientName);
                    }
                    else
                    {
                        Log("请输入正确的十六进制字符串");
                    }


                }
            }

        }

        public virtual async Task<bool> SendMsgAsync(string msg)
        {
            await Task.Delay(10);
            return false;
        }
        public virtual async Task<bool> SendDataAsync(byte[] bytes, bool isLog = true)
        {
             await Task.Delay(10);
            return false;
          
        }
        public class ConnectParams : BindableBase
        {
            private CommunicationDataType _DataType;
            /// <summary>
            /// Comment
            /// </summary>
            public CommunicationDataType DataType
            {
                get { return _DataType; }
                set
                {
                    if (_DataType != value)
                    {
                        Prompt = "已修改，请保存";
                    }
                    SetProperty(ref _DataType, value);
                }

            }


            private string _Prompt;
            [JsonIgnore]
            /// <summary>
            /// 提示
            /// </summary>
            public string Prompt
            {
                get { return _Prompt; }
                set { SetProperty(ref _Prompt, value); }
            }
        }
        public enum StateEnum
        {
            Init,
            Receive,
            Sleep
        }
    }

}
